#include "conexiones.h"
#include "hilodeconexion.h"
#include "MapaParser.h"
#include "ParserDeJugadas.h"
#include "JuegoServerImp.h"
#include <fstream>
#include <iostream>
#include "Mapa.h"
#include "NotificadorDeCambios.h"
#include "FabricaDeTerritoriosObservables.h"
#include "FabricaDeJugadores.h"
#include "TiradorDeDadosDesdeArchivo.h"
#include "NormalModeServer.h"
#include "DebugModeServer.h"
#include "valparamslincmds.h"
#include "MensajeDeFinalizacion.h"
#include <cstdlib>

using namespace red;
using namespace red::hilos;

int main(int argc, char *argv[]) {
	
	int t_iCantJugadores = 0;
	string t_sArchXmlDelMapa = "";
	string t_sArchDebug = "";
	string t_sArchTiradas = "";
	
	if (ValParamsLinCmds::bParsearParams(argc, argv, t_iCantJugadores, t_sArchXmlDelMapa, t_sArchDebug, t_sArchTiradas)) {
		NotificadorDeCambios notificadorDeCambios;
	    FabricaDeTerritoriosObservables fabricaDeTerritorios(&notificadorDeCambios);
	    Mapa unMapa(&fabricaDeTerritorios);
		MapaParser mapaParser(&unMapa);
	    mapaParser.parse_file(t_sArchXmlDelMapa);
		if (!mapaParser.isParseoCorrecto()) {
			cout<<"Se encontro un problema al parsear el xml del mapa. La aplicacion ha finalizado."<<endl;
			return -1;
		}
	    if (t_sArchDebug == "") {
	    	
	    	TiradorDeDados tiradorDeDados;
		Conexiones t_Conexiones;
		size_t found = t_sArchXmlDelMapa.find_last_of("/");
		string rutaImagen = t_sArchXmlDelMapa.substr(0, found+1);
		rutaImagen.append(mapaParser.getPathImagen());
		NormalModeServer server(t_Conexiones,rutaImagen,t_sArchXmlDelMapa);
		FabricaDeJugadores fabricaDeJugadores(&notificadorDeCambios);
		JuegoServerImp juego(t_iCantJugadores,&unMapa,&tiradorDeDados,&server,&fabricaDeJugadores);
			notificadorDeCambios.setJuego(&juego);
		notificadorDeCambios.setServer(&server);
		juego.addObserver(&notificadorDeCambios);
		HiloDeConexion t_HiloDeConexion(t_iCantJugadores, t_Conexiones, &juego);
	
		
		t_HiloDeConexion.start();
		
		string t_sComando;
		string t_sComandoQ = "q";
		string t_sComandoQuit = "quit";

		do {
			getline(cin, t_sComando);
		} while ( !((t_sComando.find(t_sComandoQ) != string::npos) && (t_sComando.length() == t_sComandoQ.length()))
			 && !((t_sComando.find(t_sComandoQuit) != string::npos) && (t_sComando.length() == t_sComandoQuit.length())));
		//Si el server no fue terminado, quiere decir que se esta terminando desde la linea de comandos.
		//entonces tengo que mandar el mensaje de finalizacion a todos los clientes.
		if (!server.getTerminado()) {
			MensajeDeFinalizacion mensaje("El server ha sido cerrado");
			server.broadcast(mensaje);
			server.setTerminado();
			juego.finalizar();
		}
		server.finalizar();
		t_HiloDeConexion.cancel();
	}
	else {
		TiradorDeDadosDesdeArchivo tiradorDeDados(t_sArchTiradas);
		DebugModeServer server;
		FabricaDeJugadores fabricaDeJugadores(&notificadorDeCambios);
		JuegoServerImp juego(t_iCantJugadores,&unMapa,&tiradorDeDados,&server,&fabricaDeJugadores);
			notificadorDeCambios.setJuego(&juego);
		notificadorDeCambios.setServer(&server);
		juego.addObserver(&notificadorDeCambios);
		ParserDeJugadas parser(&juego);
		parser.parse_file(t_sArchDebug);
	    }
	}

	return 0;
}
